package com.hksj.app.websocket;


import cn.hutool.http.HttpStatus;
import com.alibaba.fastjson.JSONObject;
import com.hksj.call.dto.AskForHelpBroadcastDTO;
import com.hksj.call.entity.AskForHelp;
import com.hksj.call.entity.CallOrder;
import com.hksj.call.service.AskForHelpService;
import com.hksj.call.service.CallOrderService;
import com.hksj.common.config.utils.SpringContextUtil;
import com.hksj.data.thing.DataService;
import com.hksj.data.thing.RawData;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

@Component
@ServerEndpoint("/ws/server")
public class PanelWebsocketServer {
    private String code;

    /**
     * 连接建立成功调用的方法
     */
    @OnOpen
    public void onOpen(Session session) {
        String queryString = session.getQueryString();
        Map<String, String> queryMap = queryToMap(queryString);
        code = queryMap.get("ipAddr");
        if (StringUtils.hasText(code)) {
            WebsocketConnectionHolder.addSession(code,session);
            WebsocketResponse websocketResponse = new WebsocketResponse();
            websocketResponse.setType(MessageType.CONNECT_REPLY.value());
            websocketResponse.setCode(HttpStatus.HTTP_OK);
            websocketResponse.setMsg("连接成功");
            WebsocketConnectionHolder.sendMessage(code,websocketResponse);
        }else{
            WebsocketResponse websocketResponse = new WebsocketResponse();
            websocketResponse.setType(MessageType.CONNECT_REPLY.value());
            websocketResponse.setCode(HttpStatus.HTTP_INTERNAL_ERROR);
            websocketResponse.setMsg("code不能为空");
            session.getAsyncRemote().sendText(WebsocketConnectionHolder.toObjString(websocketResponse));
            try {
                session.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }


    public Map<String,String> queryToMap(String queryString){
        Map<String,String> map = new HashMap<>();
        if(StringUtils.hasText(queryString)){
            String[] split = queryString.split("&");
            for (String str : split) {
                String[] item = str.split("=");
                if (item.length == 2) {
                    map.put(item[0], item[1]);
                }
            }
        }
        return map;
    }

    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose() {
        if (code != null){
            WebsocketConnectionHolder.removeSession(code);
        }
    }

    /**
     * 发生错误时调用
     */
    @OnError
    public void onError(Session session, Throwable error) {
        error.printStackTrace();
    }


    /**
     * 收到客户端消息后调用的方法
     *
     * @param message 客户端发送过来的消息*/
    @OnMessage
    public void onMessage(String message, Session session) {
        if (Objects.equals(message,"ping")){
            session.getAsyncRemote().sendText("pong");
            return;
        }
        WebsocketResponse websocketResponse = new WebsocketResponse();
        try {
            WebsocketRequest websocketRequest = JSONObject.parseObject(message, WebsocketRequest.class);
            websocketResponse.setCode(HttpStatus.HTTP_OK);
            if (!ObjectUtils.isEmpty(websocketRequest)) {
               if (Objects.equals(websocketRequest.getType(),MessageType.REPORT_PROPERTY.value())){
                    websocketResponse.setType(MessageType.REPORT_PROPERTY_REPLY.value());
                    writeData(websocketRequest);
               }else if(Objects.equals(websocketRequest.getType(),MessageType.ASK_FOR_HELP.value())){
                    websocketResponse.setType(MessageType.ASK_FOR_HELP_REPLY.value());
                    askForHelp(websocketRequest);
               }else if (Objects.equals(websocketRequest.getType(),MessageType.CALL_CLEAR.value())){
                    websocketResponse.setType(MessageType.CALL_CLEAR_REPLY.value());
                    callToClear(websocketRequest);
               }
            }
        } catch (Exception e) {
            e.printStackTrace();
            websocketResponse.setCode(HttpStatus.HTTP_INTERNAL_ERROR);
        }finally {
            WebsocketConnectionHolder.sendMessage(code,websocketResponse);
        }
    }

    private void askForHelp(WebsocketRequest websocketRequest) {
        if (!ObjectUtils.isEmpty(websocketRequest.getData())){
            AskForHelp log = JSONObject.parseObject(websocketRequest.getData(), AskForHelp.class);
            log.setCode(code);
            AskForHelpService askForHelpService = SpringContextUtil.getBean(AskForHelpService.class);
            askForHelpService.save(log);

            WebsocketResponse askForHelp = new WebsocketResponse();
            askForHelp.setType(MessageType.ASK_FOR_HELP_BROADCAST.value());
            askForHelp.setCode(HttpStatus.HTTP_OK);
            AskForHelpBroadcastDTO askForHelpBroadcast = new AskForHelpBroadcastDTO();
            askForHelpBroadcast.setFromCode(code);
            askForHelpBroadcast.setRemark(log.getRemark());
            askForHelpBroadcast.setFromRoomName(log.getRoomName());
            askForHelp.setData(askForHelpBroadcast);
            WebsocketConnectionHolder.sendMessageOtherAll(code,askForHelp);
        }
    }

    private void callToClear(WebsocketRequest websocketRequest) {
        if (!ObjectUtils.isEmpty(websocketRequest.getData())){
            CallOrder callOrder = JSONObject.parseObject(websocketRequest.getData(), CallOrder.class);
            callOrder.setCode(code);
            CallOrderService callOrderService = SpringContextUtil.getBean(CallOrderService.class);
            callOrderService.saveCallOrder(callOrder);
        }
    }

    private void writeData(WebsocketRequest websocketRequest) {
        if (!ObjectUtils.isEmpty(websocketRequest.getData())) {
            RawData rawData = new RawData();
            rawData.setIpAddr(code);
            rawData.setTimestamp(new Date().getTime());
            JSONObject json = JSONObject.parseObject(websocketRequest.getData());
            rawData.setDataMap(json);
            DataService dataService = SpringContextUtil.getBean(DataService.class);
            if (!ObjectUtils.isEmpty(dataService)){
                dataService.write(rawData);
            }
        }
    }
}
